#include "../Source/server.hpp"
#include <fstream>

static size_t Split(const std::string &src, const std::string &seq, std::vector<std::string> *arry)
{
    int offset = 0;
    while(offset < src.size())
    {
        size_t pos = src.find(seq, offset);
        if(pos == std::string::npos)
        {
            arry->push_back(src.substr(offset));
            return arry->size();
        }
        if(pos != offset)
            arry->push_back(src.substr(offset, pos - offset));
        offset = pos + seq.size();
    }
    return arry->size();
}
void SplitTest()
{
    std::string str = "abd,,,bcd,def,,";
    std::vector<std::string> arry;
    Split(str, ",", &arry);
    for(auto &s :arry)
    {
        std::cout << "[" << s << "]\n";
    }
}

static bool ReadFile(const std::string &filename, std::string *buf)
{
    std::ifstream ifs(filename, std::ios::binary);
    if(ifs.is_open() == false)
    {
        ERR_LOG("Open File:%s Failed!!", filename.c_str());
        return false;
    }
    size_t fsize = 0;
    ifs.seekg(0, ifs.end);  // 跳转到读写位置的文件末尾
    fsize = ifs.tellg();    // 获取相较于起始的偏移量，刚好就是文件大小
    ifs.seekg(0, ifs.beg);

    buf->resize(fsize);
    ifs.read(&(*buf)[0], fsize);
    if(ifs.good() == false)
    {
        ERR_LOG("Read File:%s Failed!!", filename.c_str());
        ifs.close();
        return false;
    }
    ifs.close();
    return true;
}
void ReadFileTest()
{
    std::string buf;
    ReadFile("./any.cpp", &buf);
    std::cout << buf.c_str() << std::endl;
}

static bool WriteFile(const std::string &filename, const std::string &buf)
{
    // trunc选项代表不需要文件原有内容
    std::ofstream ofs(filename, std::ios::binary | std::ios::trunc);
    if(ofs.is_open() == false)
    {
        ERR_LOG("Open File:%s Failed!!", filename.c_str());
        return false;
    }           
    ofs.write(buf.c_str(), buf.size());
    if(ofs.good() == false)
    {
        ERR_LOG("Write File:%s Failed!!", filename.c_str());
        ofs.close();
        return false;
    }
    ofs.close();
    return true;
}
void TestWriteFile()
{
    std::string str = "TestWrite Insert Twice";
    WriteFile("./testwrite.cpp", str);
}
void TestReadAndWriteFile()
{
    std::string str;
    ReadFile("./any.cpp", &str);
    WriteFile("./testwrite.cpp", str);
}

static char HexToI(char c)
{
    if(c >= '0' && c <= '9')
    {
        return (c - '0');
    }
    else if(c >= 'a' && c <= 'z')
    {
        return (c - 'a' + 10);
    }
    else if(c >= 'A' && c <= 'Z')
    {
        return (c - 'A' + 10);
    }
    else
    {
        return -1;
    }
}
static std::string URLEncode(const std::string &url, bool convert_space_to_plus)
{
    std::string res;
    for(auto &c : url)
    {
        if(c == ' ' && convert_space_to_plus)
        {
            res += '+';
            continue;
        }
        if(c == '.' || c == '-' || c == '_' || c == '~'|| isalnum(c))
        {
            res += c;
            continue;
        }
        char tmp[4] = {0};
        snprintf(tmp, 4, "%%%02X", c);
        res += tmp;
    }
    return res;
}
void TestURLEncode()
{
    std::string str = "/index.html ? word=c++";
    std::string res = URLEncode(str, false);
    std::cout << res << std::endl;
}

static std::string URLDecode(const std::string &url, bool convert_plus_to_space)
{
    std::string res;
    for(int i = 0; i < url.size(); i++)
    {
        if(url[i] == '%')
        {
            char v1 = HexToI(url[i + 1]);
            char v2 = HexToI(url[i + 2]);
            char v = (v1 << 4) + v2;
            res += v;
            i += 2;
            continue;
        }
        if(url[i] == '+' && convert_plus_to_space)
        {
            res += ' ';
            continue;
        }
        res += url[i];
    }
    return res;
}
void TestURLDecodeAndEncode()
{
    std::string str = "/index.html ? word=c++";
    std::string code = URLEncode(str, true);
    std::string decode = URLDecode(code, true);
    std::cout << code << std::endl;
    std::cout << decode << std::endl;
}

int main()
{
    // ReadFileTest();
    // TestWriteFile();
    // TestReadAndWriteFile();
    // TestURLEncode();
    TestURLDecodeAndEncode();
    return 0;
}